﻿using System;
using Fabrication.Tests.TestClasses;
using NUnit.Framework;

namespace Fabrication.Tests
{
    [TestFixture]
    public class date_rules
    {
        [Test]
        public void should_use_future_date()
        {
            var builtItem = new FabricationScope().Setup<SinglePropertyClass<DateTime>>()
                .For(x => x.Value).UseFutureDate(30)
                .Generate();

            Assert.That(builtItem.Value, Is.InRange(DateTime.Today, DateTime.Today.AddDays(30)));
        }

        [Test]
        public void should_use_historic_date()
        {
            var builtItem = new FabricationScope().Setup<SinglePropertyClass<DateTime>>()
                .For(x => x.Value).UseHistoricDate(30)
                .Generate();

            Assert.That(builtItem.Value, Is.InRange(DateTime.Today.AddDays((-30)), DateTime.Today));
        }

        [Test]
        public void should_use_day_range()
        {
            var builtItem = new FabricationScope().Setup<SinglePropertyClass<DateTime>>()
                .For(x => x.Value).UseRange(5)
                .Generate();

            Assert.That(builtItem.Value, Is.InRange(DateTime.Today.AddDays((-5)), DateTime.Today.AddDays(5)));
        }

        [Test]
        public void should_use_specific_range_if_first_date_is_before_second()
        {
            var builtItem = new FabricationScope().Setup<SinglePropertyClass<DateTime>>()
                .For(x => x.Value).UseRange(DateTime.Today.AddDays(-10), DateTime.Today.AddDays(1))
                .Generate();

            Assert.That(builtItem.Value, Is.InRange(DateTime.Today.AddDays((-10)), DateTime.Today.AddDays(1)));
        }

        [Test]
        public void should_use_specific_range_if_first_date_is_after_second()
        {
            var builtItem = new FabricationScope().Setup<SinglePropertyClass<DateTime>>()
                .For(x => x.Value).UseRange(DateTime.Today.AddDays(2), DateTime.Today.AddDays(1))
                .Generate();

            Assert.That(builtItem.Value, Is.InRange(DateTime.Today.AddDays(1), DateTime.Today.AddDays(2)));
        }

        [Test]
        public void should_use_single_date_if_first_date_is_equal_to_second()
        {
            var builtItem = new FabricationScope().Setup<SinglePropertyClass<DateTime>>()
                .For(x => x.Value).UseRange(DateTime.Today.AddDays(-12), DateTime.Today.AddDays(-12))
                .Generate();

            Assert.That(builtItem.Value, Is.EqualTo(DateTime.Today.AddDays(-12)));
        }

        [Test]
        public void should_use_convention_for_due_dates()
        {
            var builtItem = new FabricationScope().Generate<DateConventions>();

            Assert.That(builtItem.DateDue, Is.InRange(DateTime.Today, DateTime.Today.AddDays(8).AddSeconds(-1)));
            Assert.That(builtItem.DueDate, Is.InRange(DateTime.Today, DateTime.Today.AddDays(8).AddSeconds(-1)));
        }

        [Test]
        public void should_use_convention_for_recieved_dates()
        {
            var builtItem = new FabricationScope().Generate<DateConventions>();

            Assert.That(builtItem.DateReceived, Is.InRange(DateTime.Today.AddDays(-7), DateTime.Today.AddSeconds(-1)));
            Assert.That(builtItem.ReceivedDate, Is.InRange(DateTime.Today.AddDays(-7), DateTime.Today.AddSeconds(-1)));
        }

        [Test]
        public void should_use_today_if_no_date_rule_defined()
        {
            var builtItem = new FabricationScope().Generate<SinglePropertyClass<DateTime>>();

            Assert.That(builtItem.Value, Is.EqualTo(DateTime.Today));
        }
    }

    class DateConventions
    {
        public DateTime DueDate { get; set; }
        public DateTime DateDue { get; set; }

        public DateTime DateReceived { get; set; }
        public DateTime ReceivedDate { get; set; }
    }
}
